package com.njtoyo.taxi.admin.service.data.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.njtoyo.taxi.admin.handler.FilterHandler;
import com.njtoyo.taxi.admin.handler.common.DateIntervalHandler;
import com.njtoyo.taxi.admin.library.Const;
import com.njtoyo.taxi.admin.mapper.secondary.entity.data.DashboardIncomeDaily;
import com.njtoyo.taxi.admin.mapper.secondary.enums.DataIncomeThroughType;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.data.DashboardIncomeDailyMapper;
import com.njtoyo.taxi.admin.rest.presenter.data.chart.RankChartItemPresenter;
import com.njtoyo.taxi.admin.rest.presenter.data.data_analysis.IncomeChartPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.data.chart.ChartQueryWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.data.data_analysis.ChartWrapper;
import com.njtoyo.taxi.admin.service.data.IncomeService;
import com.taxi.entity.common.RestResult;
import com.njtoyo.taxi.entity.backend.AdminUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thymeleaf.util.ListUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@DS(Const.SECONDARY_DS)
public class IncomeServiceImpl implements IncomeService {

    @Autowired
    private DashboardIncomeDailyMapper dashboardIncomeDailyMapper;

    @Override
    public RestResult<List<IncomeChartPresenter>> incomeChart(AdminUser adminUser, ChartWrapper wrapper) {

        if (Objects.isNull(wrapper.getStartTime()) || Objects.isNull(wrapper.getEndTime())) {
            return RestResult.failed("开始时间或结束时间不能为空");
        }

        if (wrapper.getEndTime().before(wrapper.getStartTime())) {
            return RestResult.failed("开始时间不能晚于结束时间");
        }

        if (!wrapper.getEndTime().before(DateUtil.beginOfDay(DateUtil.date()))) {
            return RestResult.failed("结束时间需早于今日");
        }
        FilterHandler filterHandler = new FilterHandler(adminUser, wrapper.getCantonId(), wrapper.getCompanyId());
        List<DashboardIncomeDaily> income = getIncomeChartData(filterHandler, wrapper.getStartTime(), wrapper.getEndTime());

        List<IncomeChartPresenter> res = new ArrayList<>();
        Date current = wrapper.getStartTime();
        while (current.before(DateUtil.offsetDay(wrapper.getEndTime(), 1))) {
            IncomeChartPresenter item = new IncomeChartPresenter();
            item.setStatsDate(current);
            Date finalCurrent = current;

            BigDecimal amount = BigDecimal.valueOf(0);
            List<DashboardIncomeDaily> online = income.stream().filter(i -> {
                return i.getStatsDate().equals(finalCurrent) &&
                        i.getThroughType().equals(DataIncomeThroughType.online);
            }).collect(Collectors.toList());
            if (!ListUtils.isEmpty(online)) {
                amount = online.get(0).getTotal();
            }
            item.setTotal(amount);
            amount = BigDecimal.valueOf(0);
            List<DashboardIncomeDaily> offline = income.stream().filter(i -> {
                return i.getStatsDate().equals(finalCurrent) &&
                        i.getThroughType().equals(DataIncomeThroughType.offline);
            }).collect(Collectors.toList());
            if (!ListUtils.isEmpty(offline)) {
                amount = offline.get(0).getTotal();
            }
            item.setCashTotal(amount);

            res.add(item);
            current = DateUtil.offsetDay(current, 1);
        }

        return RestResult.success(res);
    }

    @Override
    public RestResult chart(AdminUser adminUser, ChartQueryWrapper wrapper) {
        FilterHandler filterHandler = new FilterHandler(adminUser, wrapper.getCantonId(), wrapper.getCompanyId());
        DateIntervalHandler intervalHandler = new DateIntervalHandler(wrapper.getDateGroupType(), wrapper.getInterval(), wrapper.getStartTime(), wrapper.getEndTime());

        List<RankChartItemPresenter> res = intervalHandler.getDateList();
        res.forEach(r -> {
            QueryWrapper<DashboardIncomeDaily> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("is_imitate", filterHandler.getIsImitates())
                    .eq("through_type", DataIncomeThroughType.all)
                    .eq(Objects.nonNull(wrapper.getCantonId()), "canton_id", wrapper.getCantonId())
                    .isNotNull(Objects.isNull(wrapper.getCantonId()), "canton_id")
                    .between("stats_date", DateUtil.formatDate(r.getStart()), DateUtil.formatDate(r.getEnd()))
                    .select("IFNULL(SUM(value), 0)");

            r.setTotal(dashboardIncomeDailyMapper.selectObjs(queryWrapper).get(0));
        });

        return RestResult.success(res);
    }

    /**
     * 获取收入趋势图
     *
     * @return
     */
    private List<DashboardIncomeDaily> getIncomeChartData(FilterHandler filterHandler, Date startTime, Date endTime) {
        QueryWrapper<DashboardIncomeDaily> queryWrapper = new QueryWrapper<>();

        queryWrapper.in("is_imitate", filterHandler.getIsImitates());
        queryWrapper.select("SUM(value) as total, stats_date, through_type");
        queryWrapper.in("through_type", DataIncomeThroughType.online, DataIncomeThroughType.offline);

        switch (filterHandler.getFilterType()) {
            case canton:
                queryWrapper.in("canton_id", filterHandler.getCantonIds());
                break;
            case company:
                queryWrapper.in("company_id", filterHandler.getCompanyIds());
        }

        String start = DateUtil.formatDate(startTime);
        String end = DateUtil.formatDate(endTime);

        queryWrapper.between("stats_date", start, end);
        queryWrapper.groupBy("stats_date, through_type");
        queryWrapper.orderByAsc("stats_date");
        List<DashboardIncomeDaily> res = dashboardIncomeDailyMapper.selectList(queryWrapper);

        // 翻倍率
        Double ride = filterHandler.getFakeMultiple().getRide();
        if (Objects.nonNull(ride)) {
            for (DashboardIncomeDaily item : res) {
                BigDecimal rideBD = new BigDecimal(ride);
                item.setTotal(rideBD.multiply(item.getTotal()));
            }
        }

        return res;
    }

}
